﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ManagerHabitant : MonoBehaviour {

	// Properties
	//
	//

	public Manager Manager;

	public float CoefficientHabitant;

	public List<Habitant> Habitants = new List<Habitant> ();

	public GameObject HabitantPrefab;


	//
	private float PlateauHeight = 125f;
	private float PlateauWidth = 150f;

	private int WantedHabitants = 10; 

	private float AnimationIntervalle = 0.2f;
	private float TempsAnimation = 3f;


	// Methods
	//
	//

	public void UpdateNombreHabitant()
	{
		this.WantedHabitants = Mathf.FloorToInt(this.Manager.Population / this.CoefficientHabitant);

		// If there is too much habitant
		if (this.Habitants.Count > WantedHabitants)
		{
			// Calcul du temps d'intervalle
			this.AnimationIntervalle = this.TempsAnimation/ Mathf.Abs(this.WantedHabitants - this.Habitants.Count);

			//Debug.Log ("ManagerHabitant.updateNombreHabitant - Animation Intervalle = "+this.AnimationIntervalle);

			this.StartCoroutine("CoroutineDepopHabitant");
		}

		// If there is not enough
		else if (this.Habitants.Count < WantedHabitants)
		{
			// Calcul du temps d'intervalle
			this.AnimationIntervalle = this.TempsAnimation/ Mathf.Abs(this.WantedHabitants - this.Habitants.Count);

			//Debug.Log ("ManagerHabitant.updateNombreHabitant - Animation Intervalle = "+this.AnimationIntervalle);

			this.StartCoroutine("CoroutinePopHabitant");
		}
	}

	// Same as above, but do the operation instantanly
	public void UpdateNombreHabitantInstant()
	{
		this.WantedHabitants = Mathf.FloorToInt(this.Manager.Population / this.CoefficientHabitant);
		
		// If there is too much habitant
		if (this.Habitants.Count > WantedHabitants)
		{
			// Calcul du temps d'intervalle
			this.AnimationIntervalle = this.TempsAnimation/ Mathf.Abs(this.WantedHabitants - this.Habitants.Count);
			
			//Debug.Log ("ManagerHabitant.updateNombreHabitant - Animation Intervalle = "+this.AnimationIntervalle);
			
			this.DepopHabitantsInstant();
		}
		
		// If there is not enough
		else if (this.Habitants.Count < WantedHabitants)
		{
			// Calcul du temps d'intervalle
			this.AnimationIntervalle = this.TempsAnimation/ Mathf.Abs(this.WantedHabitants - this.Habitants.Count);
			
			//Debug.Log ("ManagerHabitant.updateNombreHabitant - Animation Intervalle = "+this.AnimationIntervalle);
			
			this.PopHabitantInstant();
		}
	}


	public void UpdateMoodHabitants()
	{
		// Pour tout les habitants, on leurs demande d'updater leur niveau de mood
		foreach(Habitant h in this.Habitants){
			if(h != null){
				h.UpdateMoodLevel(this.Manager.Mood);
			}
		}
	}

	public void Reset()
	{

	}

	// Private Methods
	//
	//

	private void PopHabitant()
	{
		GameObject go = (GameObject)GameObject.Instantiate(this.HabitantPrefab);

		float x = Random.Range(-this.PlateauWidth, this.PlateauWidth);
		float y = Random.Range(-this.PlateauHeight, this.PlateauHeight);
		// While the random value are incorrect
		if( !this.isPositionAtLowerGround(new Vector2(x,y)))
		{
			x = Random.Range(-this.PlateauWidth, this.PlateauWidth);
			y = Random.Range(-this.PlateauHeight, this.PlateauHeight);
		}

		go.transform.position = new Vector3(x, -0.5f, y);

		// Tell the habitant his mood level
		go.GetComponent<Habitant>().UpdateMoodLevel(this.Manager.Mood);

		// Add him in the list
		this.Habitants.Add(go.GetComponent<Habitant>());
	}

	private void DepopHabitant(Habitant hab)
	{
		if(hab != null){
			GameObject.Destroy(hab.gameObject);
		}
	}


	private bool isPositionAtLowerGround(Vector2 pos)
	{
		// Send a raycast from the top to check if this is lower or higher ground
		RaycastHit hit;
		if (Physics.Raycast(new Vector3(pos.x, 100, pos.y), -Vector3.up, out hit))
		{
			if(hit.point.y == 0)
				return true;
			else
				return false;
		}
		return false;
	}

	IEnumerator CoroutineDepopHabitant() {
		for(int i= WantedHabitants; i<this.Habitants.Count; i++){
			this.DepopHabitant(this.Habitants[i]);
			yield return new WaitForSeconds(this.AnimationIntervalle);
		}

		this.Habitants.RemoveRange(WantedHabitants, this.Habitants.Count - WantedHabitants);

	}

	IEnumerator CoroutinePopHabitant() {

		for(int i=this.Habitants.Count; i<WantedHabitants ;i ++){
			this.PopHabitant();
			yield return new WaitForSeconds(this.AnimationIntervalle);
		}

	}

	private void DepopHabitantsInstant(){
		for(int i= WantedHabitants; i<this.Habitants.Count; i++){
			this.DepopHabitant(this.Habitants[i]);
		}

		this.Habitants.RemoveRange(WantedHabitants, this.Habitants.Count - WantedHabitants);
	}

	private void PopHabitantInstant() {
		
		for(int i=this.Habitants.Count; i<WantedHabitants ;i ++){
			this.PopHabitant();
		}
		
	}

}
